
/**单例设计模式-懒汉
 * 线程安全，lazy
 * @author weiZhiLin
 * @version 1.0
 * @date 2019/12/26 14:41
 */
public class SingletonLazy {
    /*
    采用 volatile 关键字修饰也是很有必要的， singletonLazy = new SingletonLazy(); 这段代码其实是分为三步执行：

    1) 为 singletonLazy 分配内存空间
    2) 初始化 singletonLazy
    3) 将 singletonLazy 指向分配的内存地址

    但是由于 JVM 具有指令重排的特性，执行顺序有可能变成 1>3>2。
    指令重排在单线程环境下不会出现问题，但是在多线程环境下会导致一个线程获得还没有初始化的实例。

    例如，线程 T1 执行了 1 和 3，此时 T2 调用 getInstance() 后发现 singletonLazy 不为空，
    因此返回 singletonLazy，但此时 singletonLazy 还未被初始化。

    使用 volatile 可以禁止 JVM 的指令重排，保证在多线程环境下也能正常运行。
     */
    private static volatile SingletonLazy singletonLazy;

    public static SingletonLazy getInstance() {
        if (singletonLazy == null) {
            synchronized (SingletonLazy.class) {
                if (singletonLazy == null) {
                    singletonLazy = new SingletonLazy();
                }
            }
        }
        return singletonLazy;
    }
}
